using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.Data;
using System.Net.NetworkInformation;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Forms;
using RawSocketEx;

namespace DoExitWin
{
    public partial class TimerUserControl : UserControl
    {
        public TimerUserControl()
        {
            InitializeComponent();
        }

        [StructLayout(LayoutKind.Sequential, Pack = 1)]
        internal struct TokPriv1Luid
        {
            public int Count;
            public long Luid;
            public int Attr;
        }

        [DllImport("kernel32.dll", ExactSpelling = true)]
        internal static extern IntPtr GetCurrentProcess();

        [DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)]
        internal static extern bool OpenProcessToken(IntPtr h, int acc, ref IntPtr phtok);

        [DllImport("advapi32.dll", SetLastError = true)]
        internal static extern bool LookupPrivilegeValue(string host, string name, ref long pluid);

        [DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)]
        internal static extern bool AdjustTokenPrivileges(IntPtr htok, bool disall,
        ref TokPriv1Luid newst, int len, IntPtr prev, IntPtr relen);

        [DllImport("user32.dll", ExactSpelling = true, SetLastError = true)]
        internal static extern bool ExitWindowsEx(int flg, int rea);


        internal const int SE_PRIVILEGE_ENABLED = 0x00000002;
        internal const int TOKEN_QUERY = 0x00000008;
        internal const int TOKEN_ADJUST_PRIVILEGES = 0x00000020;
        internal const string SE_SHUTDOWN_NAME = "SeShutdownPrivilege";
        internal const int EWX_LOGOFF = 0x00000000;
        internal const int EWX_SHUTDOWN = 0x00000001;
        internal const int EWX_REBOOT = 0x00000002;
        internal const int EWX_FORCE = 0x00000004;
        internal const int EWX_POWEROFF = 0x00000008;
        internal const int EWX_FORCEIFHUNG = 0x00000010;

        private static void DoExitWin(int flg)
        {
            TokPriv1Luid tp;
            IntPtr hproc = GetCurrentProcess();
            IntPtr htok = IntPtr.Zero;
            OpenProcessToken(hproc, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, ref htok);
            tp.Count = 1;
            tp.Luid = 0;
            tp.Attr = SE_PRIVILEGE_ENABLED;
            LookupPrivilegeValue(null, SE_SHUTDOWN_NAME, ref tp.Luid);
            AdjustTokenPrivileges(htok, false, ref tp, 0, IntPtr.Zero, IntPtr.Zero);
            ExitWindowsEx(flg, 0);
        }

        private void StatusCheckBox_CheckedChanged(object sender, EventArgs e)
        {
            timer1.Interval = int.Parse(textBox1.Text) * 60 * 1000;
            timer1.Enabled = StatusCheckBox.Enabled;
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            try
            {
                var process = Process.GetProcessById(int.Parse(PIdLabel.Text));
                var ipHelper = new IpHelper();
                var tcpConnections = ipHelper.GetAllTcpConnections();
                var procConnections = Array.FindAll(tcpConnections, (x) => x.owningPid == process.Id && x.state == TcpState.Established);
                if (procConnections.Length == 0)
                {
                    DoExitWin(EWX_SHUTDOWN);
                }
            }
            catch (Exception)
            {
                DoExitWin(EWX_SHUTDOWN);
            }
        }

        public void SetPid(int pid)
        {
            PIdLabel.Text = pid.ToString();
            var ipHelper = new IpHelper();
            var tcpConnections = ipHelper.GetAllTcpConnections();
            var procConnections = Array.FindAll(tcpConnections, (x) => x.owningPid == pid && x.state == TcpState.Established);
            OnLineCheckBox.Checked = procConnections.Length > 0;
        }

        public void Disabled()
        {
            timer1.Enabled = false;
        }
    }
}
